#include "utils.h"
#include <iostream>
#include <sstream>
#include <vector>
using namespace std;
bool isNumber(string s);
bool IsOp(char ch)
{
    return ch == '*' || ch == '/' || ch == '+' || ch == '-' || ch == '(' || ch == ')' || ch == '>' || ch == '<' || ch=='^' || ch=='%';
}
bool isFunction(string s)
{
    if (s.empty())
        return false;
    if (s[0] == '(')
        return false;
    while (!IsOp(s[0]))
    {
        s.erase(0, 1);
        if (s.empty())
            return false;
    }
    if (s[0] != '(')
    {
        return false;
    }
    int count = 0;
    for (int i = 0; i < s.size(); i++)
    {
        if (s[i] == '(')
        {
            count++;
        }
        else if (s[i] == ')')
        {
            count--;
        }
        if (count < 0 || (count == 0 && i != s.size() - 1))
            return false;
    }
    return count == 0;
}
bool isSymbol(string s)
{
    if (isFunction(s))
    {
        return false;
    }
    for (auto i : s)
    {
        if (IsOp(i))
        {
            return false;
        }
    }
    return true;
}
int getPriority(char ch)
{
    //获取优先级
    if (ch == '(')
        return 0;
    else if (ch == '+' || ch == '-')
        return 2;
    else if (ch == '*' || ch == '/' || ch=='%' || ch=='^')
        return 3;
    else if (ch == '>' || ch == '<')
        return 1;
    else
        return 5;
}
//remove space, strings strong!
void removeSpace(string &kekab)
{
    int size = kekab.length();
    for (int i = 0; i < size; i++)
    {
        if (kekab[i] == '\t' || kekab[i] == ' ')
        {
            kekab.erase(i, 1);
            i--;
        }
    }
}

vector<int> findEye(string src)
{
    vector<int> Eyes;
    Eyes.resize(4);
    int mid;
    int count = 0;
    for (int i = 0; i < src.size(); i++)
    {
        if (src[i] == '(')
        {
            count++;
        }
        else if (src[i] == ')')
        {
            count--;
        }
        if (src[i] == '?' && !count)
        {
            mid = i;
            Eyes[1] = mid;
            break;
        }
    }
    count = 0;
    for (int i = mid - 1; i >= 0; i--)
    {
        if (src[i] == ')')
        {
            count++;
        }
        else if (src[i] == '(')
        {
            count--;
        }
        if (count == 0)
        {
            Eyes[0] = i;
            break;
        }
    }
    count = 0;
    int end;
    for (int i = mid; i < src.size(); i++)
    {
        if (src[i] == '(')
        {
            count++;
        }
        else if (src[i] == ')')
        {
            count--;
        }
        if (src[i] == ':' && !count)
        {
            end = i;
            Eyes[2] = end;
            break;
        }
    }
    for (int i = end + 1; i < src.size(); i++)
    {
        if (src[i] == '(')
        {
            count++;
        }
        else if (src[i] == ')')
        {
            count--;
        }
        if (count == 0)
        {
            int end2 = i;
            Eyes[3] = end2;
            break;
        }
    }
    return Eyes;
}

//to find s is or isn't a number.
bool isNumber(string s)
{
    if (s.empty())
    {
        return false;
    }
    else
    {
        if ((s[0] < '0' || s[0] > '9') && s[0] != '-')
        {
            return false;
        }
        int count = 0;
        s.erase(0, 1);
        for (auto i : s)
        {
            if (i == '.')
            {
                if (count)
                    return false;
                count++;
            }
            if (((i < '0' || i > '9') && i != '.'))
            {
                return false;
            }
        }
    }
    return true;
}

//you must remove its head before eating it.
void removeHeadSpace(string &ant)
{
    int size = ant.length();
    for (int i = 0; i < size; i++)
    {
        if (ant[i] == '\t' || ant[i] == ' ')
        {
            ant.erase(i, 1);
            i--;
        }
        else
        {
            break;
        }
    }
}

//to find whether a string contains a char.
bool contain(string s, char a)
{
    for (auto i : s)
    {
        if (i == a)
        {
            return true;
        }
    }
    return false;
}

//whether target begins with head, make sure target has no space or tab prefix!
bool beginWith(string &target, string head)
{
    removeHeadSpace(target);
    if (head.length() > target.length())
    {
        return false;
    }
    int size = head.size();
    for (int i = 0; i < size; i++)
    {
        if (target[i] != head[i])
        {
            return false;
        }
    }
    return true;
}

bool looseBalance(string src)
{
    int count = 0;
    for (int i = 0; i < src.size(); i++)
    {
        if (src[i] == '(')
        {
            count++;
        }
        else if (src[i] == ')')
        {
            count--;
        }
    }
    return count == 0;
}

bool balance(string src)
{
    int count = 0;
    bool begin = false;
    for (int i = 0; i < src.size(); i++)
    {
        if (src[i] == '(')
        {
            begin = true;
            count++;
        }
        else if (src[i] == ')')
        {
            begin = true;
            count--;
        }
        if ((!count && i != src.size() - 1 && begin) || count < 0)
        {
            return false;
        }
    }
    return count == 0;
}

//split.
vector<string> myGet(string src, char delim);
//to get the formal list of a function call.
vector<string> pureFormals(string s)
{
    if (!balance(s))
        throw "Not valid function calling:" + s;
    removeSpace(s);
    vector<string> res;
    string temp;
    for (int i = 0; i < s.size(); i++)
    {
        if (s[i] != '(')
        {
            s.erase(i, 1);
            i--;
        }
        else
        {
            s.erase(i, 1);
            break;
        }
    }
    if (s.empty())
        return {};
    s.erase(s.size() - 1, 1);

    auto buffer = myGet(s, ',');
    for (auto temp : buffer)
    {
        res.push_back(temp);
    }
    return res;
}

vector<string> myGet(string src, char delim)
{
    vector<string> res;
    string temp = "";
    int count = 0;
    for (auto i : src)
    {
        if (count == 0 && delim == i)
        {
            res.push_back(temp);
            temp = "";
        }
        else
        {
            temp += i;
        }
        if (i == '(')
        {
            count++;
        }
        else if (i == ')')
        {
            count--;
        }
    }
    if (!temp.empty())
        res.push_back(temp);
    return res;
}

//wheel.
string &replace_all_distinct(string &str, const string &old_value, const string &new_value)
{
    for (string::size_type pos(0); pos != string::npos; pos += new_value.length())
    {
        if ((pos = str.find(old_value, pos)) != string::npos)
        {
            str.replace(pos, old_value.length(), new_value);
        }
        else
        {
            break;
        }
    }
    return str;
}
